iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 16
0

成品連結:Mouse Move Shadow操作前程式碼完成後程式碼

今天要做的是當滑鼠移動時,文字影子(text-shadow)跟著移動的效果,那就開始吧!

可以看到目前頁面上有一個 div.hero,包著 h1 在裡面,而且 h1 當中的內容是可編輯的!這是因為 h1 中有 contenteditable="true" 的屬性使然。

設定監聽事件

首先先監聽要操作的元素,當滑鼠移動時執行 shadow

const hero = document.querySelector('.hero');
const text = hero.querySelector('h1');

hero.addEventListener('mousemove', shadow);

滑鼠移動到 h1 區塊時座標會不正常?

如果你試著在 shadow 中寫入 console.log(e.offsetX, e.offsetY),會發現當滑鼠移動到 h1 時座標會異常變化,仔細看會得知這時的 e.offsetX & e.offsetYe 變成了 h1 而不是 .hero;因此當滑入 h1 左上角時e.offsetX & e.offsetY 皆會變成 0。

解決辦法是判斷當進入 h1e.offsetX & e.offsetY 變成 h1.target.offsetLeft 以及 h1.target.offsetTop

但在這之前我們要將 e.offsetX & e.offsetY 存入變數,以利在進入 h1 時可以作變動

function shadow(e) {
    let {offsetX: x, offsetY: y} = e;  // ES6 Destructuring
    if (this !== e.target) {  // this 指的是 .hero,這裡 if 的意思是當滑鼠進入 h1 時
      x += e.target.offsetLeft;  // 這裡的 e 是 h1 不是 .hero
      y += e.target.offsetTop;
      
    }
}

稍微說明一下,如果 e.heroe.target.offsetLeft & e.target.offsetTop 一直都會是 0,因為這兩個屬性是指相對於最接近的父層容器左邊及上方的距離。這樣講或許有些抽象,相關資訊可以參考下方連結的 HTMLElement.offsetLeft 以及 HTMLElement.offsetParent。

製作陰影

現在有了座標了,接著來做陰影吧!
目前畫面上預設有黑色的陰影,如果試著設定 text.style.textShadow = ${x}px ${y}px 10px rgba(0,0,0,1) 會發現陰影會移動,但並不如成品般圍繞著文字移動而已,而是有時候會超出頁面範圍。

因此我們要設定陰影所能移動的範圍

例如我們想要陰影最大移動的距離是 100px,也就是向上/下/左/右各 100px,因此我們先設定移動距離

const walk = 200; // 200px

接著就要計算如何讓陰影無論移動向哪個方向距離都是 100px,我們會需要用到 .hero 的常、寬,這裡已經先算好了

function shadow(e) {
    // 省略上方 code
    const {offsetWidth: width, offsetHeight: height} = hero;
    const xWalk = Math.round((x / width * walk) - (walk / 2));
    const yWalk = Math.round((y / height * walk) - (walk / 2));
}

假設左上角座標是(0,0)、右下角是(1000,800),寬剛分別為 1000、600,則算出來的 xWalkyWalk 分別會是 -100、-100 以及 100, 100

接著再設定 CSS textShadow 屬性即可,如要設定多個陰影用逗號隔開即可

text.style.textShadow = `${xWalk}px ${yWalk}px 10px rgba(155,119,93,0.7), ${-xWalk}px ${-yWalk}px 10px rgba(240,226,205,0.7)`

Reference


上一篇
JS30 Day 15 - LocalStorage
下一篇
JS30 Day 17 - Sort Without Articles
系列文
一起挑戰 JavaScript 30 吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言